package engine

import (
	"github.com/kataras/golog"
	"sdn-executor/core/netconf"
	"sdn-executor/model/common"
	model "sdn-executor/model/netconf"
	"sdn-executor/storage/sql/executor"
	"sdn-executor/utils/erros"
)

// ExecuteNetconf 执行netconf命令
func ExecuteNetconf(m *Message) *model.Result {

	requestId := m.RequestId
	err := executor.UpdateSdnExecutorResultStatusByRequestIdAndOrder(requestId, 0, string(common.ExecStatusExecuting))
	if err != nil {
		return buildNetconfFailResult(requestId, "", err)
	}

	query := m.Request.(*model.Query)
	device := query.Device

	client, err := netconf.NewClient(device, query.Port, query.User, query.Password)
	if err != nil {
		golog.Errorf("netconf.NewClient failed. device: %s, requestId: %s, err: %+v", device, requestId, err)
		executor.FailSdnExecutorResult(requestId, 0, "", err.Msg)
		return buildNetconfFailResult(requestId, "", err)
	}
	defer client.Close()

	// 发送命令
	results, err := client.SendAndReceive(query)
	if err != nil {
		golog.Errorf("client.SendAndReceive failed. device: %s, requestId: %s, err: %+v", device, requestId, err)
		e := executor.FailSdnExecutorResult(requestId, 0, string(results), err.Msg)
		if e != nil {
			golog.Errorf("sql.FailSdnExecutorResult failed. results: %s, device: %s, requestId: %s, err: %+v",
				string(results), device, requestId, e)
		}
		return buildNetconfFailResult(requestId, string(results), err)
	}

	e := executor.SuccessSdnExecutorResult(requestId, 0, string(results))
	if e != nil {
		golog.Errorf("sql.SuccessSdnExecutorResult failed. results: %s, device: %s, requestId: %s, err: %+v",
			string(results), device, requestId, e)
	}
	return buildNetconfSuccessResult(requestId, string(results))
}

func buildNetconfFailResult(requestId string, result string, err *erros.Error) *model.Result {
	return &model.Result{
		Code:      err.Code,
		Msg:       err.Msg,
		RequestId: requestId,
		Status:    common.ExecStatusFail,
		RpcReply:  result,
	}
}

func buildNetconfSuccessResult(requestId string, result string) *model.Result {
	return &model.Result{
		Code:      erros.OK.Code,
		Msg:       erros.OK.Msg,
		RequestId: requestId,
		Status:    common.ExecStatusSuccess,
		RpcReply:  result,
	}
}
